#pragma once
#include <WinSock2.h>
#include <vector>
#include <map>
#include <memory>
#include <string>
#include <deque>
#include <functional>
#include "base.h"
#include "NetBase.h"


class NetServer;
class NetConnection;
class ClinetConnection;
class Packet;

class NetWork
{
public:
	enum
	{
		State_None,
		State_Noraml,
		State_Stopping,
		State_Stopped,
	};
	enum
	{
		Opt_Accept,
		Opt_Recive,
		Opt_Send,
		Opt_Connect,
		Opt_Disconnect,
	};

	NetWork();
	~NetWork();
	bool Start();
	void Stop();
	void Stop(ServerID id);

	//for Server
	bool         AddServer(ServerID id,int nPort,Accepted_Handler _handler);
	bool         SendPacket(ServerID _sid,ConectionID _cid,Packet* packet);
	Packet*      PopPacket(ServerID _sid,ConectionID _cid);

	//for Clienter
	ConectionID  AddClient();
	void		 RemoveClient(ConectionID id);
	bool	     Connect(ConectionID id,const char* pIP,int nPort);
	bool         Asyn_Connect(ConectionID id,const char* pIP,int nPort,Connected_Handler _conHandler);
	bool         SendPacket(ConectionID cid,Packet* packet);
	Packet*      PopPacket(ConectionID cid);

private:
	ClinetConnection* _getConnection(ConectionID id);
	static unsigned int _stdcall  WorkRoutine(void* data);
	static unsigned int _stdcall Maintain(void* data);
	bool Maintain_Callback();
	bool WorkRoutine_Callback();
	std::tr1::shared_ptr<NetServer> GetServer(ServerID id);
	int  GetServerCount();

	typedef std::map<ConectionID/*ConnectionID*/,ClinetConnection*> MAP_CONNECTION;
	typedef MAP_CONNECTION::iterator MAP_CONNECTION__ITER;
	typedef std::vector<shared_ptr<NetServer>>			  SERVER_SET;
	typedef std::vector<shared_ptr<NetServer>>::iterator SERVER_SET_ITER;

	SERVER_SET m_vecServer;
	My_CriticalSection m_ServerCritical;
	MAP_CONNECTION m_mapClientContion;
	My_CriticalSection m_ContionCritical;

	HANDLE m_IOCP;
	std::vector<HANDLE> m_vecWorkThread;
	HANDLE m_maintainThread;
	int    m_state;
	HANDLE m_stopEvent;
	ConIDGenerator m_IDGenerator;

	Work_Func m_workFunc;
	NetPlatform m_platform;
};
